package advanced.design_mode;

import advanced.design_mode.adaptermode.AdvancedUsbAdapter;
import advanced.design_mode.adaptermode.Client;
import advanced.design_mode.adaptermode.Keyboard;
import advanced.design_mode.adaptermode.UsbAdapter;
import advanced.design_mode.buildermode.AirShip;
import advanced.design_mode.buildermode.SxtAirShipBuilder;
import advanced.design_mode.buildermode.SxtAirShipDircetor;
import advanced.design_mode.decoratemode.Coffee;
import advanced.design_mode.decoratemode.Drink;
import advanced.design_mode.decoratemode.Milk;
import advanced.design_mode.decoratemode.Sugar;
import advanced.design_mode.factorymode.BMW;
import advanced.design_mode.factorymode.Car;
import advanced.design_mode.factorymode.CarFactory;
import advanced.design_mode.observermode.ConcreateSubject;
import advanced.design_mode.observermode.ObserverA;
import advanced.design_mode.observermode.ReactiveFlowApp;
import advanced.design_mode.prototypemode.Sheep;
import advanced.design_mode.proxymode.ProxyStar;
import advanced.design_mode.proxymode.RealStar;
import advanced.design_mode.proxymode.Star;
import advanced.design_mode.proxymode.StarHandler;
import advanced.design_mode.strategymode.Context;
import advanced.design_mode.strategymode.NewCustomerFewStrategy;
import advanced.design_mode.strategymode.NewCustomerManyStrategy;
import advanced.design_mode.templatemode.DrawMoney;
import org.junit.Test;

import java.lang.reflect.Proxy;
import java.util.Date;


public class Main {
    @Test
    public void 工厂模式测试() {
        Car bmw = CarFactory.create(BMW.class);
        if (bmw != null) System.out.println("create successful");
    }

    @Test
    public void 静态代理模式测试() {
        RealStar realStar = new RealStar("周杰伦");
        ProxyStar proxyStar = new ProxyStar(realStar);
        proxyStar.confer();
        proxyStar.sing();
    }

    @Test
    public void 动态代理模式测试() {
        RealStar jj = new RealStar("JJ");
        Star proxy = (Star) Proxy.newProxyInstance(getClass().getClassLoader(), new Class[]{Star.class}, new StarHandler(jj));
        proxy.confer();
        proxy.sing();
        System.out.println(proxy.toString());
    }

    @Test
    public void 模板模式测试() {
        DrawMoney drawMoney = new DrawMoney();
        drawMoney.process();
    }

    @Test
    public void 观察者模式测试() {
        //目标对象
        ConcreateSubject concreateSubject = new ConcreateSubject();
        //创建多个观察者
        ObserverA observerA = new ObserverA();
        ObserverA observerA1 = new ObserverA();
        ObserverA observerA2 = new ObserverA();
        concreateSubject.register(observerA);
        concreateSubject.register(observerA1);
        concreateSubject.register(observerA2);
        //改变subject的状态
        concreateSubject.setState(3000);
    }

    @Test
    public void 测试使用Flow写的观察者模式() throws Exception {
        ReactiveFlowApp app = new ReactiveFlowApp();

        System.out.println("\n\n### CASE 1: Subscribers are fast, buffer size is not so " +
                "important in this case.");
        app.magazineDeliveryExample(100L, 100L, 8);

        System.out.println("\n\n### CASE 2: A slow subscriber, but a good enough buffer " +
                "size on the publisher's side to keep all items until they're picked up");
        app.magazineDeliveryExample(1000L, 3000L, ReactiveFlowApp.NUMBER_OF_MAGAZINES);

        System.out.println("\n\n### CASE 3: A slow subscriber, and a very limited buffer " +
                "size on the publisher's side so it's important to keep the slow " +
                "subscriber under control");
        app.magazineDeliveryExample(1000L, 3000L, 8);

    }

    @Test
    public void 测试适配器模式() {
        Client client = new Client();
        UsbAdapter usbAdapter = new UsbAdapter();
        client.typeWord(usbAdapter);
        //2 使用接口方式来实现适配功能, 避免了类继承的缺点
        AdvancedUsbAdapter advancedUsbAdapter = new AdvancedUsbAdapter(new Keyboard());
        client.typeWord(advancedUsbAdapter);

    }

    @Test
    public void 测试策略模式() {
        Context few = new Context(new NewCustomerFewStrategy());
        Context many = new Context(new NewCustomerManyStrategy());
        few.printPrice(1000);
        many.printPrice(1000);

    }

    @Test
    public void 测试创建者模式() {
        SxtAirShipDircetor sxtAirShipDircetor = new SxtAirShipDircetor(new SxtAirShipBuilder());
        AirShip airShip = sxtAirShipDircetor.create();
        System.out.println(airShip);

    }

    @Test
    public void 测试原型模式() throws CloneNotSupportedException {
        Date date = new Date();
        Sheep s1 = new Sheep("小丽", date);
        System.out.println(s1);
        System.out.println(s1.getName() + " " + s1.getBirthday());
        //s1 和s2 对象不一样 ,但是值一样

        //这种情况 是浅克隆,  只是把s1的值和对象的引用给了s2,
        //如果s1种修改了引用对象的值, s2也会改变, 会产生纠葛
        //解决: 需要重写sheep的clone方法, 在里边把date属性也克隆, 而不是默认的克隆date对象的引用
        Sheep s2 = (Sheep) s1.clone();
        date.setTime(23254235235l);
        System.out.println("s1=" + s1.getBirthday());
        System.out.println("s2=" + s2.getBirthday());
        System.out.println(s2);
        System.out.println(s2.getName() + " " + s2.getBirthday());

    }

    @Test
    public void 测试装饰器模式() {
        Drink coffee = new Coffee();
        Sugar sugar = new Sugar(coffee);
        sugar.degree();
        System.out.println(sugar.info() + "--->" + sugar.cost());


        Drink milk = new Milk(coffee);
        System.out.println(milk.info() + "--->" + milk.cost());


        milk = new Milk(sugar);
        System.out.println(milk.info() + "---->" + milk.cost());
    }
}
